//Application.h
//Created 17/08/13
//Created By Daniel Bowler
//
//This class will be created in WinMain(). It will init the window
//properties (and storing useful win data), and create our manager classes - 
//which may (or may not) create other data (eg the GraphicsManager will
//create D3D11 resources for the backbuffer / DSV)
//
//This class will also handle the message loop - passing messages
//to the requred scene (or graphics manager or the applications
//Resize function)
//
//Standard singleton design pattern on show here. 
//
//Modified: 25/11/13 By Daniel Bowler: Class creates and destroys our
//Graphics Interface. Creates it after the graphics manager. 

#pragma once

//Required for Win32 applications - the basis required for a D3D application.
#include <Windows.h>
//Used to calculate delta.
#include "GameTimer.h"
//For std::wstring
#include <string>
//For GET_Y_LPARAM and GET_X_LPARAM within message handling function
#include <WindowsX.h>
//For wostringstream
#include "d3dUtil.h"

//Forward declare manager classes - we only use pointers in the .h
class SceneManager;
class GraphicsManager;
//Modified: 25/11/13: Now manages the GraphicsInterface class
class GraphicsInterface;
//App now creates / destroys collision manager
class CollisionManager;

//Initial window sizes - The theory is that the window size will be
//always initially set to these sizes and resized after D3D has been initilised
//to the users settings. 
#define INITIALWINDOWHEIGHT 720
#define INITIALWINDOWWIDTH 1280

class Application
{
public:
	//Make this class a singleton
	//
	//Returns a pointer to our shared application instance - when first
	//called, it will create the instance in memory.
	static Application* GetInstance();
	//Release function - called right at the end of the applications
	//life
	void Release();

	//Init function - will create our window (800x600 at the start)
	//and create our singletons.
	void Init(HINSTANCE inst);

	//Returns true if the class has been instantiated. 
	static bool IsInit();
	
	//***GAME LOOP***
	//Enters the main game loop. When this returns, the application
	//will begin the closing process (Ie, calls Release() above).
	//Calculates deltamanages timer updates scene, renders scene, 
	//calculates FPS statistics & outputs them to the main window, dispatches messages.
	//Returns (wParam) when WM_QUIT message is recived
	int Run();

	//***WINDOWS MESSAGE LOOP
	//The global messaging function will forward messages to this function
	LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
public:
	//Function that returns the aspect ratio
	float ReturnClientAspectRatio() const {return clientAspectRatio;};
	//Functions that return the width and height of the window
	int ReturnClientWidth() {return clientWidth;};
	int ReturnClientHeight() {return clientHeight;};

	//Function to return a pointer to the main game timer
	GameTimer* ReturnGameLoopTimer(){return &mainGameLoopTimer;};

	//Function that returns the main window handle
	HWND MainWindowHandle() { return mainWnd;};
private:
	//Called when the window is resized. Will have to manage some Direct3D
	//resources. 
	void OnResize();

	//Function that creates the main window
	void InitMainWindow();

	//Works out FPS and updates the window to show this. 
	void CalculateFrameRateStats();

	//***MOUSE INPUT***
	// handling mouse input. We will forward the input to the sceneManager
	//which will in turn forward the input to the current scene. 
	void OnMouseDown(WPARAM btnState, int x, int y, UINT originalMessage);
	void OnMouseUp(WPARAM btnState, int x, int y, UINT originalMessage);
	void OnMouseMove(WPARAM btnState, int x, int y);

	//Our timer will be used to calculate the delta which can be used
	//when updating a scene. 
	GameTimer mainGameLoopTimer;

	//State of the window and game loop. 
	bool      appPaused;
	bool      minimized;
	bool      maximized;
	bool      resizing;

	//application Instance handle - passed from WinMain
	HINSTANCE appInstance;
	//Main window handle.
	HWND            mainWnd; 
	std::wstring    initialWindowCaption; //will be changed to current scene title
	int             clientWidth;
	int             clientHeight;
	float           clientAspectRatio;

	//Manager classes.
	SceneManager* sharedSceneManager;
	GraphicsManager* sharedGraphicsManager;
	GraphicsInterface* sharedGraphicsInterface;

	//Game management
	CollisionManager* sharedCollisionManager;

private:
	//Make this class a singleton
	//
	//Instance shared between every class that requires it
	static Application* instance;

	//Disable constructor/destructor/assignment operator/copy constrcutor
	//forcing the programmer to use my GetInstacne() and Release() functions.
	Application();
	~Application();
	Application(Application& other);
	Application& operator=(Application& other);
};